package de.dailab.graphworld.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import de.dailab.jiactng.agentcore.SimpleAgentNode;

public class GraphWorldLauncher extends JFrame implements ActionListener{

	private static final long serialVersionUID = 6996666612374481832L;
	
	JRadioButton rb5x5, rb10x10, rblaod, rbedit;
	JComboBox agentNumber1, agentNumber2, agentType, agentView;
	JTextField agentsPerNode, filename;
	JButton fileChooser, finished;
	JLabel agentLabel1, agentLabel2, agentTypeLabel, agentViewLabel, agentMaxLabel, fileLabel;
	
	public GraphWorldLauncher(){
		
		// RadioButtons
		JPanel rbPanel = new JPanel(new GridLayout(2,2));
		setupRadioButtons();
		rbPanel.add(rb5x5);
		rbPanel.add(rb10x10);
		rbPanel.add(rblaod);
		rbPanel.add(rbedit);
		
		// ComboBox for #Agents
		JPanel agentPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		agentLabel1 = new JLabel("Select the number of agents:  ");
		agentLabel2 = new JLabel("   Collectors:");
		String[] comboText1 = {"1","2","3","4","5","6","7","8","9","10"};
		String[] comboText2 = {"1","2","3","4","5","6","7","8","9","10"};
		agentNumber1 = new JComboBox(comboText1);
		agentNumber2 = new JComboBox(comboText2);
		agentPanel.add(agentLabel1);
		agentPanel.add(agentNumber1);		
		agentPanel.add(agentLabel2);
		agentPanel.add(agentNumber2);
		
		// ComboBox for Agent type
		JPanel agentTypePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		agentTypeLabel = new JLabel("Select the agent type:");
		String[] comboTypeText = {"Random","Swarm","Contracting","Brokering"};
		agentType = new JComboBox(comboTypeText);
		agentType.addActionListener(this);
		agentType.setActionCommand("type");
		agentTypePanel.add(agentTypeLabel);
		agentTypePanel.add(agentType);
		
		// ComboBox for Agent viewrange
		JPanel agentViewPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		agentViewLabel = new JLabel("Select the agent view range:");
		String[] comboViewText = {"Wumpus","One Neighbor","All Neighbors"};
		agentView = new JComboBox(comboViewText);
		agentViewPanel.add(agentViewLabel);
		agentViewPanel.add(agentView);
		
		// TextField for #Agents per node
		JPanel agentMaxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		agentMaxLabel = new JLabel("Select the maximum number of agents allowed per node:\n");
		agentsPerNode = new JTextField("1000");
		agentsPerNode.setColumns(3);
		agentMaxPanel.add(agentMaxLabel);
		agentMaxPanel.add(agentsPerNode);
		
		// FileChooser for loading
		JPanel chooserPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		fileLabel = new JLabel("Select a saved graph to load:");
		filename = new JTextField();
		filename.setColumns(30);
		filename.setEditable(false);
		fileChooser = new JButton("Open");
		fileChooser.setMnemonic(KeyEvent.VK_O);
		fileChooser.setActionCommand("file");
		fileChooser.addActionListener(this);
		chooserPanel.add(filename);
		chooserPanel.add(fileChooser);
		filePanel.add(fileLabel);
		
		// start button
		JPanel finishedPanel = new JPanel();
		finished = new JButton("Start");
		finished.setActionCommand("start");
		finished.addActionListener(this);
		finished.setMnemonic(KeyEvent.VK_S);
		finishedPanel.add(finished);

		// set layout and title
		this.setLayout(new BorderLayout());
		this.setTitle("GraphWorld Launcher");
		
		// set center panel
		JLabel emptyLabel1 = new JLabel(" ");
		JLabel emptyLabel2 = new JLabel(" ");
		JLabel emptyLabel3 = new JLabel(" ");
		JLabel emptyLabel4 = new JLabel(" ");
		JPanel centerPanel = new JPanel(new GridLayout(10,1));
		centerPanel.add(emptyLabel1);
		centerPanel.add(agentTypePanel);
		centerPanel.add(agentViewPanel);
		centerPanel.add(emptyLabel4);
		centerPanel.add(agentPanel);
		centerPanel.add(agentMaxPanel);
		centerPanel.add(emptyLabel2);
		centerPanel.add(filePanel);
		centerPanel.add(chooserPanel);
		centerPanel.add(emptyLabel3);
		
		// add everything
		this.add(rbPanel,BorderLayout.NORTH);
		this.add(finishedPanel,BorderLayout.SOUTH);
		this.add(centerPanel,BorderLayout.CENTER);
		
		// make stuff visible & usable
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.pack();
		agentNumber1.setEnabled(true);
		agentNumber2.setEnabled(true);
		agentType.setEnabled(true);
		agentView.setEnabled(true);
		agentsPerNode.setEditable(true);
		fileChooser.setEnabled(false);
		agentLabel1.setForeground(Color.BLACK);
		agentLabel2.setForeground(Color.BLACK);
		agentTypeLabel.setForeground(Color.BLACK);
		agentMaxLabel.setForeground(Color.BLACK);
		agentsPerNode.setForeground(Color.BLACK);
		fileLabel.setForeground(Color.GRAY);
		agentLabel2.setVisible(false);
		agentNumber2.setVisible(false);
		this.setVisible(true);
		
	}
	
	private void setupRadioButtons(){
		
		rb5x5 = new JRadioButton("Random 5x5 Grid");
		rb5x5.setMnemonic(KeyEvent.VK_5);
		rb5x5.setActionCommand("rnd");
		rb5x5.setSelected(true);

	    rb10x10 = new JRadioButton("Random 10x10 Grid");
	    rb10x10.setMnemonic(KeyEvent.VK_0);
	    rb10x10.setActionCommand("rnd");

	    rblaod = new JRadioButton("Load Graph from File");
	    rblaod.setMnemonic(KeyEvent.VK_L);
	    rblaod.setActionCommand("load");

	    rbedit = new JRadioButton("Start Editor");
	    rbedit.setMnemonic(KeyEvent.VK_C);
	    rbedit.setActionCommand("edit");

	    //Group the radio buttons.
	    ButtonGroup group = new ButtonGroup();
	    group.add(rb5x5);
	    group.add(rb10x10);
	    group.add(rblaod);
	    group.add(rbedit);

	    //Register a listener for the radio buttons.
	    rb5x5.addActionListener(this);
	    rb10x10.addActionListener(this);
	    rblaod.addActionListener(this);
	    rbedit.addActionListener(this);
	    		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// enable/disable buttons/fields depending on choices selected
		if(e.getActionCommand().equals("rnd")){
			agentNumber1.setEnabled(true);
			agentNumber2.setEnabled(true);
			agentType.setEnabled(true);
			agentView.setEnabled(true);
			agentsPerNode.setEditable(true);
			fileChooser.setEnabled(false);
			agentLabel1.setForeground(Color.BLACK);
			agentLabel2.setForeground(Color.BLACK);
			agentTypeLabel.setForeground(Color.BLACK);
			agentViewLabel.setForeground(Color.BLACK);
			agentMaxLabel.setForeground(Color.BLACK);
			agentsPerNode.setForeground(Color.BLACK);
			fileLabel.setForeground(Color.GRAY);
		} else if(e.getActionCommand().equals("load")){
			agentNumber1.setEnabled(true);
			agentNumber2.setEnabled(true);
			agentType.setEnabled(true);
			agentView.setEnabled(true);
			agentsPerNode.setEditable(true);
			fileChooser.setEnabled(true);
			agentLabel1.setForeground(Color.BLACK);
			agentLabel2.setForeground(Color.BLACK);
			agentTypeLabel.setForeground(Color.BLACK);
			agentViewLabel.setForeground(Color.BLACK);
			agentMaxLabel.setForeground(Color.BLACK);
			agentsPerNode.setForeground(Color.BLACK);
			fileLabel.setForeground(Color.BLACK);
		} else if(e.getActionCommand().equals("edit")){
			agentNumber1.setEnabled(false);
			agentNumber2.setEnabled(false);
			agentType.setEnabled(false);
			agentView.setEnabled(false);
			agentsPerNode.setEditable(false);
			fileChooser.setEnabled(false);
			agentLabel1.setForeground(Color.GRAY);
			agentLabel2.setForeground(Color.GRAY);
			agentTypeLabel.setForeground(Color.GRAY);
			agentViewLabel.setForeground(Color.GRAY);
			agentMaxLabel.setForeground(Color.GRAY);
			agentsPerNode.setForeground(Color.GRAY);
			fileLabel.setForeground(Color.GRAY);
		} else if(e.getActionCommand().equals("file")){
			JFileChooser filePath = new JFileChooser();
			int retVar = filePath.showOpenDialog(this);
			if (retVar == JFileChooser.APPROVE_OPTION) {
				filename.setText(filePath.getSelectedFile().getPath());
				// TODO validate
			}
		} else if(e.getActionCommand().equals("type")){
			JComboBox cb = (JComboBox)e.getSource();
	        String type = (String)cb.getSelectedItem();
	        if(type.equals("Contracting") || type.equals("Brokering")){
	        	agentLabel1.setText("Select the number of Explorers:  ");
	    		agentLabel2.setVisible(true);
	    		agentNumber2.setVisible(true);
	        } else {
	        	agentLabel1.setText("Select the number of agents:  ");
	    		agentLabel2.setVisible(false);
	    		agentNumber2.setVisible(false);
	        }
		} else if(e.getActionCommand().equals("start")){
			if(rbedit.isSelected()){
				@SuppressWarnings("unused")
				GraphWorldGUI gui = new GraphWorldGUI(true);
				this.dispose();
			} else {
				createXML();
				SimpleAgentNode.main(new String[] { "classpath:GraphWorld.xml" });
				this.dispose();
			}
		} else {
			JOptionPane.showMessageDialog(this,"Something went wrong.","Error",JOptionPane.ERROR_MESSAGE);
		}
	}

	// write xml to set all variables for simulation
	private void createXML() {
		File output = new File("src"+File.separator+"main"+File.separator+"resources"+File.separator+"GraphWorldAgent.xml");
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(output));
			bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
			bw.write("<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\" \"http://www.springframework.org/dtd/spring-beans.dtd\">\n");
			bw.write("<beans>\n");
			bw.write("<import resource=\"classpath:de/dailab/jiactng/agentcore/conf/Agent.xml\" />\n");
			bw.write("<bean name=\"GraphWorldAgent\" parent=\"SimpleAgent\">\n");
			bw.write("<property name=\"agentBeans\">\n");
			bw.write("<list>\n");
			bw.write("<ref bean=\"WorldAgentBean\" />\n");
			bw.write("</list>\n");
			bw.write("</property>\n");
			bw.write("</bean>\n");
			bw.write("<bean name=\"WorldAgentBean\" class=\"de.dailab.graphworld.world.GraphWorldAgentBean\">\n");
			bw.write("<property name=\"size\" value=\"25\" />\n");
			bw.write("<property name=\"viewrange\" value=\"");
			if(((String)agentView.getSelectedItem()).equals("Wumpus"))
				bw.write("0");
			else if(((String)agentView.getSelectedItem()).equals("One Neighbor"))
				bw.write("1");
			else if(((String)agentView.getSelectedItem()).equals("All Neighbors"))
				bw.write("2");
			else
				System.err.println("Selecting agent viewrange went wrong!");
			bw.write("\" />\n");
			bw.write("<property name=\"agentsPerNode\" value=\""+Integer.parseInt(agentsPerNode.getText())+"\" />\n");
			bw.write("</bean>\n");
			bw.write("<bean name=\"RandomAgent\" parent=\"SimpleAgent\">\n");
			//bw.write("<bean name=\"SwarmAgent\" parent=\"SimpleAgent\">\n");
			bw.write("<property name=\"agentBeans\">\n");
			bw.write("<list>\n");
			bw.write("<ref bean=\"RandomBean\"/>\n");
			//bw.write("<ref bean=\"SwarmBean\"/>\n");
			bw.write("</list>\n");
			bw.write("</property>\n");
			bw.write("</bean>\n");
			bw.write("<bean name=\"RandomBean\" class=\"de.dailab.graphworld.bean.RandomBean\">\n");
			//bw.write("<bean name=\"SwarmBean\" class=\"de.dailab.graphworld.bean.SwarmBean\">\n");
			bw.write("<property name=\"logLevel\" value=\"DEBUG\" />\n");
			bw.write("<property name=\"executeInterval\" value=\"1000\" />\n");
			bw.write("<property name=\"agentsPerNode\" value=\""+Integer.parseInt(agentsPerNode.getText())+"\" />\n");
			bw.write("<property name=\"viewrange\" value=\"");
			if(((String)agentView.getSelectedItem()).equals("Wumpus"))
				bw.write("0");
			else if(((String)agentView.getSelectedItem()).equals("One Neighbor"))
				bw.write("1");
			else if(((String)agentView.getSelectedItem()).equals("All Neighbors"))
				bw.write("2");
			else
				System.err.println("Selecting agent viewrange went wrong!");
			bw.write("\" />\n");
			bw.write("</bean>\n");
			bw.write("</beans>\n");
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}